package pATT.bNEdit.base;

import java.io.Serializable;
import java.util.Enumeration;
import java.util.Observable;
import java.util.Observer;
import java.util.Vector;

/**
 * <p>Title: BNEdit</p>
 * <p>Description: Bayesian Network Editor</p>
 * <p>Copyright: Copyright (c) 2004</p>
 * <p>Company: </p>
 * @author Martin Blech
 * @version 1.0
 */

public class ExperienceTable implements Observer, Serializable {
  /**
	 * 
	 */
	private static final long serialVersionUID = 1L;
private Vector table;
  private Nodo node;
  double initialExperience;

  public static final double DEFAULT_INITIAL_EXPERIENCE = 1;

  /**
   * Create a new ExperienceTable for the given node and with the given
   * initial experience.
   * @param node Nodo
   * @param initialExperience double
   */
  public ExperienceTable(Nodo node, double initialExperience) {
    this.node = node;
    this.initialExperience = initialExperience;
    initializeTable();
    node.addObserver(this);
  }

  /**
   * Create a new ExperienceTable for the given node and with the default
   * initial experience.
   * @param node Nodo
   */
  public ExperienceTable(Nodo node) {
    this(node, DEFAULT_INITIAL_EXPERIENCE);
  }

  @SuppressWarnings("unchecked")
private void initializeTable() {
    int n = 1;
    Enumeration enumStates =
        node.getProbabilidadOriginal().getDominio().getEstados().elements();
    enumStates.nextElement();
    while (enumStates.hasMoreElements()) {
      n *= ( (Integer) enumStates.nextElement()).intValue();
    }
    table = new Vector();
    for (int i=0; i<n; i++) {
      table.add(new Double(initialExperience));
    }
  }

  public int getTableIndexForStateIndexes(Vector stateIndexes) {
    int tableIndex = 0;
    int tableSize = table.size();
    Enumeration enumStates =
        node.getProbabilidadOriginal().getDominio().getEstados().elements();
    enumStates.nextElement();
    Enumeration enumStateIndexes = stateIndexes.elements();
    while (enumStates.hasMoreElements() && enumStateIndexes.hasMoreElements()) {
      int numStates = ((Integer)enumStates.nextElement()).intValue();
      int stateIndex = ((Integer)enumStateIndexes.nextElement()).intValue();
      tableSize /= numStates;
      tableIndex += tableSize * stateIndex;
    }
    return tableIndex;
  }

  @SuppressWarnings("unchecked")
public Vector getStateIndexesForTableIndex(int index) {
    Vector states = new Vector();
    int tableSize = table.size();
    Enumeration enumStates =
        node.getProbabilidadOriginal().getDominio().getEstados().elements();
    enumStates.nextElement();
    while (enumStates.hasMoreElements()) {
      int n = ((Integer)enumStates.nextElement()).intValue();
      tableSize /= n;
      int stateIndex = index / tableSize;
      states.add(new Integer(stateIndex));
      index %= tableSize;
    }
    return states;
  }

  /**
   * Whenever a parent is added or deleted, the table should be reinitialized
   *
   * @param o Observable
   * @param arg Object
   */
  public void update(Observable o, Object arg) {
    String option=(String)(((Vector)arg).get(0));
    if (option.equals("ParentAdded") ||
        option.equals("ParentDeleted"))
      initializeTable();
  }

  /**
   * Unregister itself from the node's observer list.
   */
  public void finalize() {
    node.deleteObserver(this);
  }

  /**
   * Get the experience count for the given configuration
   * @param stateIndexes Vector - indexes for the sates of all of the node's
   * parents
   * @return double - the state count for the given configuration
   */
  public double get(Vector stateIndexes) {
    int index = getTableIndexForStateIndexes(stateIndexes);
    return ((Double)table.get(index)).doubleValue();
  }

  public double get(int index) {
    return ((Double)table.get(index)).doubleValue();
  }

  /**
   * Set the experience count for the given configuration
   * @param stateIndexes Vector - indexes for the states of all of the node's
   * parents
   * @param experienceCount double - the new experience count for the given
   * configuration
   */
  @SuppressWarnings("unchecked")
public void set(Vector stateIndexes, double experienceCount) {
    int index = getTableIndexForStateIndexes(stateIndexes);
    table.set(index, new Double(experienceCount));
  }
  @SuppressWarnings("unchecked")
  public void set(int index, double experienceCount) {
    table.set(index, new Double(experienceCount));
  }

  /**
   * Increment the experience count for the given configuration by the given
   * experience increment.
   * @param stateIndexes Vector - indexes for the states of all of the node's
   * parents
   * @param experienceIncrement double - the experience increment-
   */
  public void increment(Vector stateIndexes, double experienceIncrement) {
    set(stateIndexes, get(stateIndexes) + experienceIncrement);
  }

  public void increment(int index, double experienceIncrement) {
    set(index, get(index) + experienceIncrement);
  }
}
